package com.cskaoyan.gateway.controller.promo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cskaoyan.gateway.cache.CacheManager;
import com.google.common.util.concurrent.RateLimiter;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.promo.PromoService;
import com.mall.promo.constant.PromoRetCode;
import com.mall.promo.dto.*;
import com.mall.user.annotation.Anoymous;
import com.mall.user.intercepter.TokenIntercepter;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

/*
 * @description: 秒杀的相关请求
 */
@Slf4j
@RestController
@RequestMapping("/shopping")
public class SecKillController {

    @Reference(timeout = 3000, retries = 0, check = false)
    private PromoService promoService;

    @Autowired
    CacheManager cacheManager;

    // 通过该工具，来实现令牌桶算法，实现限流
    private RateLimiter rateLimiter;

    // 线程池
    private ExecutorService executorService;

    @PostConstruct
    public void init() {
        // 创建一个每秒产生100个令牌的令牌桶
        rateLimiter = this.rateLimiter.create(100);

        executorService = Executors.newFixedThreadPool(100);
    }


    /*
     * @description: 获得秒杀商品列表
     * @return: com.mall.commons.result.ResponseData
     * @author: mabinbin
     * @date: 2021/8/30
     */
    @GetMapping("/seckilllist")
    @Anoymous
    public ResponseData secKillList(PromoInfoRequest promoInfoRequest) {

        String yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(new Date());
        promoInfoRequest.setYyyymmdd(yyyyMMdd);

        PromoInfoResponse promoInfoResponse = promoService.getPromoList(promoInfoRequest);
        if (promoInfoResponse.getCode().equals(PromoRetCode.SUCCESS.getCode())) {
            return new ResponseUtil().setData(promoInfoResponse);
        }
        return new ResponseUtil().setErrorMsg(promoInfoResponse.getMsg());
    }


    /*
     * @description: 获得秒杀商品详情页
     * @return: com.mall.commons.result.ResponseData
     * @author: mabinbin
     * @date: 2021/8/30
     */
    @PostMapping("/promoProductDetail")
    public ResponseData promoProductDetail(@RequestBody PromoProductDetailRequest request) {

        PromoProductDetailResponse productDetail = promoService.getPromoProductDetail(request);
        if (productDetail.getCode().equals(PromoRetCode.SUCCESS.getCode())) {
            return new ResponseUtil().setData(productDetail);
        }
        return new ResponseUtil().setErrorMsg(productDetail.getMsg());
    }

    /*
     * @description: 秒杀下单（普通版）
     * @return: com.mall.commons.result.ResponseData
     * @author: mabinbin
     * @date: 2021/8/30
     */
    @PostMapping("/seckill")
    public ResponseData secKill(@RequestBody CreatePromoOrderRequest createPromoOrderRequest, HttpServletRequest request) {


        // 总体的请求限流(令牌桶来做)
        // 如果获取令牌成功，继续向下正常执行，需要等待一段时间
        rateLimiter.acquire();

        //限流处理
        Long productId = createPromoOrderRequest.getProductId();
        Long psId = createPromoOrderRequest.getPsId();
        // 先判断有没有售罄
        String key =  "stock_not_enough" + psId + "_" + productId;

        //业务限流的工作
        String s = cacheManager.checkCache(key);
        if (s != null && "notEnough".equals(s.trim())) {
            return new ResponseUtil<>().setErrorMsg("商品售罄");
        }


        //封装请求
        String userInfo = (String) request.getAttribute(TokenIntercepter.USER_INFO_KEY);
        JSONObject object = JSON.parseObject(userInfo);
        Long uid = Long.parseLong(object.get("uid").toString());
        String username = (String) object.get("username");
        createPromoOrderRequest.setUserId(uid);
        createPromoOrderRequest.setUsername(username);

//        CreatePromoOrderResponse response = promoService.createPromoOrder(createPromoOrderRequest);
//        if (response.getCode().equals(PromoRetCode.SUCCESS.getCode())) {
//            return new ResponseUtil().setData(response);
//        }
        // 对下游服务的调用放入线程池中来执行
        Future<CreatePromoOrderResponse> future = executorService.submit(new Callable<CreatePromoOrderResponse>() {

            @Override
            public CreatePromoOrderResponse call() throws Exception {
                return promoService.createPromoOrderInTransaction(createPromoOrderRequest);
            }
        });

        CreatePromoOrderResponse response = null;
        try {
            response = future.get();
            if (PromoRetCode.SUCCESS.getCode().equals(response.getCode())) {
                return new ResponseUtil().setData(response);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return new ResponseUtil().setErrorMsg(response.getMsg());
    }
}
